package com.eagle.common.util;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.StringWriter;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

/**
 * Jackson工具包工具类
 *
 */
public class JacksonUtils {

    private static final Logger logger = LoggerFactory.getLogger(JacksonUtils.class);

    private static ObjectMapper objectMapper = new ObjectMapper();
    private static JsonFactory jsonFactory = new JsonFactory();

    static{
        //设置全局时区为中国
        objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
    }

    /**
     * @param jsonAsString
     *            jsonAsString
     *            JSON字符串
     * @param pojoClass
     *            <T> pojoClass
     *            目标映射对象类型
     * **/
    public static <T>T fromJson(String jsonAsString, Class<T> pojoClass)
    {
        try
        {
            // 如要这个string是一个array类型的json，则可以直接转换成数组类型的业务对象
            objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
            //TimeZone.getAvailableIDs();
            if (jsonAsString.startsWith(JsonToken.START_ARRAY.asString()) && jsonAsString.endsWith(JsonToken.END_ARRAY.asString()))
            {
                return objectMapper.readValue(jsonAsString, objectMapper.getTypeFactory().constructCollectionType(List.class, pojoClass));
            } else
            {
                return objectMapper.readValue(jsonAsString,pojoClass);
            }
        } catch (JsonParseException e)
        {
            if (logger.isErrorEnabled())
            {
                logger.error("JsonParseException", e);
            }
        } catch (JsonMappingException e)
        {
            if (logger.isErrorEnabled())
            {
                logger.error("JsonMappingException", e);
            }
        } catch (IOException e)
        {
            if (logger.isErrorEnabled())
            {
                logger.error("IOException", e);
            }
        }

        if (logger.isInfoEnabled())
        {
            logger.info("JSON Deserialize throw a exception，返回目标POJO");
        }
        return (T) pojoClass;
    }

    /**
     * @param  pojo
     *            业务对象
     * @param  prettyPrint
     *        设置格式输出可读性
     * @param filterClassField
     *            过滤字段
     * **/
    public static String toJson(Object pojo, boolean prettyPrint, Map< Class<?>, String[] >...filterClassField)
    {
        StringWriter sw = new StringWriter();
        JsonGenerator jg = null;
        try
        {
            jg = jsonFactory.createGenerator(sw);
            if (prettyPrint)
            {
                jg.useDefaultPrettyPrinter();
            }
            //设置过滤字段
            MapperUtil.setSerializationFilter(objectMapper,  filterClassField);
            objectMapper.writeValue(jg, pojo);
            sw.flush();
            return sw.toString();
        } catch (IOException e)
        {
            if (logger.isErrorEnabled())
            {
                logger.error("IOException", e);
            }
            e.printStackTrace();
        }

        if (logger.isInfoEnabled())
        {
            logger.info("JSON serialize throw a exception，返回空串");
        }
        return StringUtils.EMPTY;
    }

    /**
     * @param pojo
     *            业务对象
     *            默认格式输出为可读性不友好
     * **/
    public static String toJson(Object pojo)
    {
        return toJson(pojo, false);
    }

    // map to json

    /**
     * json串转换成MAP
     *
     * @param jsonStr
     * ***/
    public static Map fromJson2Map(String jsonStr)
    {
        return (Map) fromJson(jsonStr, Map.class);
    }

    /**
     *
     * MAP对象转成业务对象
     *
     * @return
     * ***/
    public static <T>T map2Bean(Map pojoMap, Class<T> pojoClass)
    {
        String pojoAsMapString = JacksonUtils.toJson(pojoMap);
        return JacksonUtils.fromJson(pojoAsMapString, pojoClass);
    }

}
